Skip to content

fix(skills): serve agent-bundle/meta to rendered skills and compile their JSX without the consumer react runtime - #527

Merged
ScriptedAlchemy merged 3 commits into
mainfrom
fix/440-441-rendered-skill-loader
Sep 4, 2026
Merged

fix(skills): serve agent-bundle/meta to rendered skills and compile their JSX without the consumer react runtime#527
ScriptedAlchemy merged 3 commits into
mainfrom
fix/440-441-rendered-skill-loader

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Fixes #440. Fixes #441.

Both defects live in the same place — how compileRenderedSkill (packages/agent-bundle/src/config/rendered-skill.ts) loads a rendered SKILL.tsx through jiti — so they ship together.

Root causes

  • Rendered SKILL.tsx cannot import agent-bundle/meta (AB3003 wrapping AB4760) #440compileRenderedSkill (rendered-skill.ts:61-73 before this PR) evaluated the module through jiti with no alias, so agent-bundle/meta resolved to the published dist/meta.js, whose every binding throws AB4760; the skill loader reported it as AB3003. Discovery runs before any bundle exists, so the compiler's specifier replacement never applied to skills.
  • inspectWorkbenchSurface fails on projects with a rendered SKILL.tsx under the react-server condition (AB3005 recentlyCreatedOwnerStacks) #441 — the same loader compiled the skill's JSX against the consumer's react/jsx-runtime. jiti resolves package subpaths with fixed ["node","require"]/["node","import"] conditions (it ignores the process's --conditions), so it loaded the client react/jsx-runtime.js; but React's own internal require("react") inside that runtime honours --conditions=react-server and returned the server build, whose shared internals lack recentlyCreatedOwnerStacks → the throw inside jsx() that inspectWorkbenchSurface surfaced as AB3005. (The issue's guess about jsx-dev-runtime was close but not exact: jiti's babel plugin uses development: false; the failing frame is react-jsx-runtime.development.js:326 because NODE_ENV is unset.)

Fix

  • New src/config/plugin-identity.ts: pluginIdentity(projectRoot, config)plugin.name, the package.json axes, and the resolved plugin version — extracted from normalizeProject (which now calls it for model.metadata), so discovery and normalization derive one identity.
  • compileRenderedSkill(source, { meta }) writes two generated modules into a private mkdtemp directory (nothing is written under the project; validate stays read-only) and passes them to jiti as alias:
    • agent-bundle/metageneratedMetaModuleSource(meta), the exact module the build injects;
    • react/jsx-runtime and react/jsx-dev-runtime → a plain element factory ({ $$typeof, type, key, props } + Fragment = Symbol.for('react.fragment')), which is all renderElementToMarkdown ever walked. The skill's own import React from 'react' still resolves from the project as before.
  • discoverProject passes projectMeta(pluginIdentity(root, config)); the Workbench SkillDocumentService passes projectMeta(model.metadata) when it re-parses source skills. parseSkill gains an optional 4th options argument.
  • Docs: docs/entry-conventions.md (meta reference), docs/diagnostics.md (AB4760 section), and the Skills authoring guide (en + zh).

Tests

  • rendered-skills.test.ts: a skill importing { meta, name, packageName, packageVersion, version } renders the identity normalizeProject stamps (package.json axes, authored plugin.version precedence), and a direct parseSkill without an identity still reports AB3003; a fixture whose node_modules/react/jsx-runtime.js throws proves the loader never resolves the consumer runtime while keyed lists and import React from 'react' still work.
  • New tests/route-unit/workbench-surface-rendered-skill.test.ts: runs in the repo's agentBundleRstest() route-unit pool (--conditions react-server, asserted) and calls inspectWorkbenchSurface on a project with a rendered skill that imports agent-bundle/meta and react — the exact inspectWorkbenchSurface fails on projects with a rendered SKILL.tsx under the react-server condition (AB3005 recentlyCreatedOwnerStacks) #441 shape. Fails on main (AB3003: Cannot find module 'agent-bundle/meta'; with the import removed, the recentlyCreatedOwnerStacks AB3005), passes here.
  • Manual: the issue repros against the packed build — agent-bundle validate renders Hello **world** from version \0.0.1`, agent-bundle buildemits it intoskills/demo/SKILL.md, and node probe.mjs/node --conditions=react-server probe.mjsboth printOK skills: 1`.
  • pnpm test:unit 3247 passed, pnpm test:route-unit 59 passed, pnpm typecheck, pnpm lint, pnpm docs:site:build clean.

Consumer follow-up

cargo-hauler's rendered skill can import version from agent-bundle/meta again (the "prints no version for now" workaround in #440), and its tests/workbench-surface.test.ts can move into the route-unit pool beside the other harness levels (the plain-pool workaround in #441).

Review status

  • Codex review of 1b1a1e1 opened one P2 thread (discover.ts:261: pluginIdentity() dereferenced config.plugin.name before validateSource, so {} / plugin: null became a generic AB7000). Addressed in fb905cb8e: discovery now uses declaredPluginIdentity(), which returns undefined for an unusable plugin.name; the skill is then served no identity (its own AB3003) and validation reports AB4000 as before — covered by a new assertion over {}, { plugin: null }, { plugin: { name: '' } }, and { plugin: 'x' }. No reply was posted on the thread by request; this note is the response.
  • First Release gates run failed in packages/workbench/tests/packed-release.e2e.test.ts ("foreground outage ledger quiet fence … net::ERR_ABORTED" during browser navigation), unrelated to this change (no skill/meta diagnostic involved; the same job passed on fix(routes): follow re-exported default components in the route contract check (AB4810) #524); re-run.
  • Last Codex-reviewed head: 1b1a1e1f0. Unreviewed heads: 0bf21b704, fb905cb8e (the review fix), then the rebase onto main after fix(routes): follow re-exported default components in the route contract check (AB4810) #524 (9a3abdd63, af5710e1e, 6d164f5a3). No @codex review was requested by instruction (no PR comments); merged on green CI per the reviewer-fallback rule.

@changeset-bot

changeset-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6d164f5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T05:44:17.229384Z 1b1a1e1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 4, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@527
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@527
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@527

commit: 6d164f5

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b1a1e1f0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Rendered skills evaluate during discovery, before normalization stamps
// the same identity into the model; `agent-bundle/meta` serves it to them
// here so a skill documents the version its plugin ships (#440).
const meta = projectMeta(pluginIdentity(projectRoot, config));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve validation for a missing plugin object

When a configuration exports {} or declares plugin: null, this unconditional identity calculation reaches pluginIdentity(), which dereferences config.plugin.name before validateSource can inspect the malformed value. ProjectService therefore converts the discovery exception into generic AB7000 instead of returning the established actionable AB4000 diagnostic; make identity derivation tolerate malformed plugin metadata so normal source validation can report it.

Useful? React with 👍 / 👎.

…heir JSX against the loader's element factory

Rendered SKILL.tsx modules evaluate through jiti during discovery, outside the
compiler's specifier replacement, so 'agent-bundle/meta' fell through to the
published module and threw AB4760 inside AB3003 (#440). The loader now aliases
the specifier to the same generated identity module the build stamps, fed from
one pluginIdentity() derivation normalization also uses for model.metadata.

The skill's JSX compiled against the consumer's react/jsx-runtime, which jiti
resolves without the process's --conditions while React's own inner
require('react') honours them; under the route-unit pool's react-server
condition the client jsx runtime met the server React and threw
(recentlyCreatedOwnerStacks) so inspectWorkbenchSurface failed with AB3005
(#441). The loader now aliases react/jsx-runtime and react/jsx-dev-runtime to
its own plain element factory: the Markdown renderer never needed React.

Fixes #440
Fixes #441
…n discovery derives the skill identity

Review: discovery dereferenced config.plugin.name before validateSource ran,
turning {} or plugin: null into a generic AB7000. declaredPluginIdentity()
returns undefined for an unusable plugin.name; the rendered skill then gets
no identity (AB3003) and validation reports AB4000 as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant